package rtti;

import java.util.*;

class Pet {}

class Dog extends Pet {}

class Dog1 extends Dog {}
class Dog2 extends Dog {}
class Dog3 extends Dog {}

class Cat extends Pet {}

class Cat1 extends Cat {}
class Cat2 extends Cat {}
class Cat3 extends Cat {}

class PetCounter extends HashMap<Class<?>, Integer> {
    public void count(Class<? extends Pet> pet) {
        increment(pet);
    }

    private void increment(Class<?> obj) {
        if(obj == null || Object.class == obj)
            return;
        Integer n = get(obj);
        put(obj, n == null ? 1 : n + 1);
        increment(obj.getSuperclass());
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (Entry<Class<?>, Integer> entry : entrySet()) {
            sb.append(entry.getKey().getSimpleName());
            sb.append("=");
            sb.append(entry.getValue());
            sb.append("\n");
        }
        return sb.toString();
    }
}

abstract class AbstractPetGenerator {
    protected abstract List<Class<? extends Pet>> types();

    private Random random = new Random();

    public Pet generate() {
        try {
            return types().get(random.nextInt(types().size())).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    public List<Pet> generateArray(int n) {
        List<Pet> pets = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            pets.add(generate());
        }
        return pets;
    }
}

class PetGenerator extends AbstractPetGenerator {

    private final List<Class<? extends Pet>> types = Arrays.asList(Dog1.class, Dog2.class, Dog3.class, Cat1.class, Cat2.class, Cat3.class);

    @Override
    protected List<Class<? extends Pet>> types() {
        return types;
    }
}

/**
 * 宠物计数
 */
public class Counter {
    public static void main(String[] args) {
        AbstractPetGenerator generator = new PetGenerator();
        List<Pet> pets = generator.generateArray(20);
        PetCounter counter = new PetCounter();
        for (Pet pet : pets) {
            counter.count(pet.getClass());
        }
        System.out.println(pets);
        System.out.println(counter);
    }
}
